/*
 * Copyright (c) 2024 Black Sesame Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>
#include "dal/domain_participant.h"
#include "dal/publisher.h"
#include "dal/topic.h"
#include "dal_rticonnextdds/converter/QosConverter.hpp"
#include "mj_interfaces/msg/mjtype.hpp"

TEST(pub_create_and_delete, test_publisher)
{
    dal_ret_t ret;
    dal_domain_participant_listener_callbacks_t participant_callbacks = { };

    dal_domain_participant_listener_t* participant_listener =
        dal_create_domain_participant_listener(participant_callbacks);

    dal_domain_participant_t* participant = dal_create_domain_participant(
        20, DAL_PARTICIPANT_QOS_DEFAULT, participant_listener, DAL_ANY_STATUS);

    dal_publisher_listener_callbacks_t pub_callbacks = { };

    dal_publisher_listener_t* pub_listener = dal_create_publisher_listener(pub_callbacks);

    dal_publisher_t* pub = dal_domain_participant_create_publisher(
        participant, DAL_PUBLISHER_QOS_DEFAULT, pub_listener, DAL_ANY_STATUS);
    EXPECT_NE(pub->handle_, nullptr);

    ret = dal_delete_publisher_listener(pub_listener);
    EXPECT_EQ(ret, DAL_RETCODE_PRECONDITION_NOT_MET);

    ret = dal_domain_participant_delete_publisher(participant, pub);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    ret = dal_delete_publisher_listener(pub_listener);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    dal_delete_domain_participant(participant);

    ret = dal_delete_domain_participant_listener(participant_listener);
    EXPECT_EQ(ret, DAL_RETCODE_OK);
}

TEST(datawriter_create_and_delete, test_publisher)
{
    dal_ret_t ret;

    dal_domain_participant_listener_callbacks_t participant_callbacks = { };

    dal_domain_participant_listener_t* participant_listener =
        dal_create_domain_participant_listener(participant_callbacks);

    dal_domain_participant_t* participant = dal_create_domain_participant(
        20, DAL_PARTICIPANT_QOS_DEFAULT, participant_listener, DAL_ANY_STATUS);

    dal_publisher_listener_callbacks_t pub_callbacks = { };

    dal_publisher_listener_t* pub_listener = dal_create_publisher_listener(pub_callbacks);

    dal_publisher_t* pub = dal_domain_participant_create_publisher(
        participant, DAL_PUBLISHER_QOS_DEFAULT, pub_listener, DAL_ANY_STATUS);

    dal_type_support_t* ts =
        dal_create_type_support((void*)(mj_interfaces::msg::Mjtype::FullyQualifiedName()));

    const char* type_name = dal_type_support_get_type_name(ts);
    ret = dal_type_support_register_type(ts, participant, type_name);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    dal_topic_listener_callbacks_t topic_callbacks = { };

    dal_topic_listener_t* topic_listener = dal_create_topic_listener(topic_callbacks);

    dal_topic_t* topic = dal_domain_participant_create_topic(participant,
                                                             "HelloWorldTopic",
                                                             type_name,
                                                             DAL_TOPIC_QOS_DEFAULT,
                                                             topic_listener,
                                                             DAL_NONE_STATUS);

    dal_datawriter_listener_callbacks_t writer_callbacks = { };

    dal_datawriter_listener_t* writer_listener = dal_create_datawriter_listener(writer_callbacks);

    dal_datawriter_t* writer = dal_publisher_create_datawriter(
        pub, topic, DAL_DATAWRITER_QOS_DEFAULT, writer_listener, DAL_ANY_STATUS);
    EXPECT_NE(writer->handle_, nullptr);

    ret = dal_delete_datawriter_listener(writer_listener);
    EXPECT_EQ(ret, DAL_RETCODE_PRECONDITION_NOT_MET);

    ret = dal_publisher_delete_datawriter(pub, writer);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    ret = dal_delete_datawriter_listener(writer_listener);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    dal_domain_participant_delete_topic(participant, topic);

    dal_delete_topic_listener(topic_listener);

    dal_delete_type_support(ts);

    dal_domain_participant_delete_publisher(participant, pub);

    dal_delete_publisher_listener(pub_listener);

    dal_delete_domain_participant(participant);

    dal_delete_domain_participant_listener(participant_listener);
}

TEST(pub_and_writer_created_with_created_default_qos, test_publisher)
{
    dal_ret_t ret;
    dal_domain_participant_qos_t* part_qos = dal_create_default_participant_qos();
    dal_publisher_qos_t* pub_qos = dal_create_default_publisher_qos();
    dal_datawriter_qos_t* writer_qos = dal_create_default_datawriter_qos();

    dal_domain_participant_t* participant =
        dal_create_domain_participant(20, part_qos, NULL, DAL_ANY_STATUS);

    dal_publisher_t* pub =
        dal_domain_participant_create_publisher(participant, pub_qos, NULL, DAL_ANY_STATUS);
    EXPECT_NE(pub, nullptr);
    EXPECT_NE(pub->handle_, nullptr);

    dal_type_support_t* ts =
        dal_create_type_support((void*)(mj_interfaces::msg::Mjtype::FullyQualifiedName()));

    const char* type_name = dal_type_support_get_type_name(ts);
    ret = dal_type_support_register_type(ts, participant, type_name);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    dal_topic_t* topic = dal_domain_participant_create_topic(
        participant, "HelloWorldTopic", type_name, DAL_TOPIC_QOS_DEFAULT, NULL, DAL_ANY_STATUS);

    dal_datawriter_t* writer =
        dal_publisher_create_datawriter(pub, topic, writer_qos, NULL, DAL_ANY_STATUS);
    EXPECT_NE(writer, nullptr);
    EXPECT_NE(writer->handle_, nullptr);

    ret = dal_publisher_delete_datawriter(pub, writer);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    ret = dal_domain_participant_delete_topic(participant, topic);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    ret = dal_domain_participant_delete_publisher(participant, pub);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    ret = dal_delete_domain_participant(participant);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    dal_delete_participant_qos(part_qos);
    dal_delete_publisher_qos(pub_qos);
    dal_delete_datawriter_qos(writer_qos);
}

TEST(delete_participant_when_pub_exists, test_publisher)
{
    dal_ret_t ret;
    dal_domain_participant_t* participant =
        dal_create_domain_participant(20, DAL_PARTICIPANT_QOS_DEFAULT, NULL, DAL_ANY_STATUS);

    dal_publisher_t* pub = dal_domain_participant_create_publisher(
        participant, DAL_PUBLISHER_QOS_DEFAULT, NULL, DAL_ANY_STATUS);

    ret = dal_delete_domain_participant(participant);
    EXPECT_NE(ret, DAL_RETCODE_OK);

    dal_domain_participant_delete_publisher(participant, pub);
    ret = dal_delete_domain_participant(participant);
    EXPECT_EQ(ret, DAL_RETCODE_OK);
}